﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Clients
{
    public partial class Form1 : Form
    { 
        private static long _userId = 0; 
        private static List<string> _ipList = new List<string>(); 
        private static ConcurrentQueue<VideoInfo> _dowList = new ConcurrentQueue<VideoInfo>();
       
        public Form1()
        { 
            log4net.Config.XmlConfigurator.Configure();
            InitializeComponent();
           
        }

        private void Form1_Load_1(object sender, EventArgs e)
        { 
            this.DataType.SelectedIndex = 0;
            timer1.Enabled = true;
            timer1.Start();

            Task.Factory.StartNew(() => { // 开起不断循环方法，执行下载任务
                while (true)
                {
                    VideoInfo temp = null;
                   
                    if (_dowList.TryDequeue(out temp) == true)
                    {
                        ThreadPool.QueueUserWorkItem(start =>
                        {
                            DownFile(temp); 
                        }); 
                    }
                } 
            }); 
        }

        #region 页面事件

        private void label1_Click(object sender, EventArgs e)
        {
            this.DataType.SelectedIndex = 1;
        }

        /// <summary>
        /// 开始处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            var startId = StringHelper.ToNumber(this.StartID.Text);
            var endID = StringHelper.ToNumber(this.EndID.Text);
            var number = StringHelper.ToNumber(this.txtNumber.Text);
           // var url = ConstHelper.GetUrl(this.DataType.SelectedIndex);
            var dataType = this.DataType.SelectedIndex;

            if (_ipList.Count == 0)
            {
                MessageBox.Show("请先设置代理IP！");
                return;
            }

            this.button1.Enabled = false;
            this.button2.Enabled = false;
            GetResourceUrl(startId, endID, number, dataType);
        }
         
        /// <summary>
        /// 选择代理服务器
        /// </summary> 
        private void button2_Click(object sender, EventArgs e)
        {
            var taskList = new List<Task>();
            DialogResult diagorel = MessageBox.Show("是否开启代理初始化检查，初始化检查会比较慢！", "请选择", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
             
            var dialog = new OpenFileDialog(); 
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                var  path = dialog.FileName.ToString(); 
                using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
                {
                    var ip = sr.ReadToEnd();
                    if (string.IsNullOrEmpty(ip) == true)
                    {
                        MessageBox.Show("文件夹无数数据！");
                        return;
                    }
                     
                    ip.Split('\n').ToList().ForEach(item =>
                    { 
                        var ipId = item.Trim(); 
                        if (string.IsNullOrEmpty(ipId) == false)
                        {
                            if (item.IndexOf('@') > -1)
                            {
                                ipId = item.Split('@')[0]; 
                            }

                            if (diagorel == DialogResult.Yes)
                            {
                                taskList.Add(Task.Factory.StartNew(() =>
                                {
                                    string content = string.Empty;
                                    if (HttpHelper.Get("http://www.sina.com/", ipId, out content))
                                    {
                                        Logging4net.WriteInfo("成功:"+ ipId);
                                        _ipList.Add(ipId);
                                    } 
                                })); 
                            }
                            else 
                            {
                                _ipList.Add(ipId);
                            }
                        }
                    });

                    Task.WaitAll(taskList.ToArray());
                    MessageBox.Show($"采集到可用{_ipList.Count}条代理ip！");  
                }

                if (diagorel == DialogResult.Yes)
                {
                    File.Delete(path); // 删除旧文件 
                    using (System.IO.StreamWriter file = new System.IO.StreamWriter(path, true))
                    {
                        foreach (string line in _ipList)
                        {
                            file.WriteLine(line);// 直接追加文件末尾，换行 
                        }
                    }
                }
            }
        }

        #endregion

        #region 获取代理IP

        /// <summary>
        /// 获取代理IP信息
        /// </summary>
        /// <param name="indexList">排除已使用过IP</param> 
        public static int GetProxyIP(params int[] indexList)
        {
            while (true)
            {
                var ip = new Random().Next(1, _ipList.Count);

                if (_ipList.Count != indexList.Length)
                {
                    if (indexList.Contains(ip) == false)
                    {
                        return ip;
                    }
                }
                else
                {
                    return -1;
                } 
            }
        }
        
        #endregion
          
        #region 采集栏目
         
        /// <summary>
        /// 只开一个线程用户数据处理
        /// </summary> 
        public static Task<bool> GetResourceUrl(long startId, long endID, long number, int dataType)
        {
            return Task.Run(() =>
            {
                for (; startId <= endID; startId++) // ID 循环
                {
                    _userId = startId;
                    GetVideoList(startId, dataType, number); // 采集数据
                }
 
                return false;  
            });
        }
         
        /// <summary>
        /// 获取采集数据
        /// </summary>
        /// <param name="id">需要采集的ID</param>
        /// <param name="dataType">类型</param>
        /// <param name="number">最大采集多少</param> 
        public static int GetVideoList(long id, int dataType, long number)
        {
            var pageIndex = 0;
            var sum = 0; // 采集总条数
            var proxyIp = new List<int>();

            do
            {
                pageIndex++;

                goUrl:
                var ip = GetProxyIP(proxyIp.ToArray()); 
                if (ip == -1) // IP 已经使用完毕
                {
                    return sum;
                }
                 
                try
                {
                    proxyIp.Add(ip); // 添加已使用IP
                    var json = string.Empty;

                    if (HttpHelper.Get(string.Format(ConstHelper.GetUrl(dataType), id, pageIndex), _ipList[ip], out json) == true)
                    {
                       
                        if (json.IndexOf("data") > -1)
                        { 
                            var models = SerializerHelper.JsonDeserialize<Videos>(json);
                            if (models.data != null && models.data.Any() == true)
                            {
                                if ((sum + models.data.Count()) > number)
                                {
                                    for (int i = 0; i < (number - sum); i++)
                                    {
                                      //  sum +=1;
                                        models.data[i].id = id.ToString();
                                        _dowList.Enqueue(models.data[i]);
                                    } 
                                     
                                    break;
                                }
                                else
                                {
                                    sum += models.data.Count;
                                    foreach (var item in models.data)
                                    {
                                        item.id = id.ToString();
                                        _dowList.Enqueue(item);
                                    }
                                } 
                            }
                        }
                        else // 未采集到数据时返回
                        {
                            return sum;
                        }
                    }
                    else
                    {
                        goto goUrl;
                    } 
                }
                catch (Exception ex)
                {
                    Logging4net.WriteError(ex); // 记录错误日志
                    goto goUrl;
                }
            } while (true);

            return sum; 
        } 

        #endregion
         
        #region 下载文件

        public static bool DownFile(VideoInfo info)
        {
            var proxyIp = new List<int>();
            var urlId = GetUrlId(info.video_url);
            var url = info.video_url.Replace(urlId, DecryptID(GetUrlId(urlId)));
           // info.id = DecryptID(GetUrlId(urlId));
            var path = $"{System.Environment.CurrentDirectory}\\{ConstHelper.GetType(info.dataType)}\\{DateTime.Now.ToString("yyyyMMdd")}\\{info.id}";

            if (url.IndexOf("http:") == -1)
            {
                url = "http:" + url;
            }

            do
            {
                var ip = GetProxyIP(proxyIp.ToArray());
                if (ip == -1) // IP 已经使用完毕
                {
                    Logging4net.WriteInfo($"下载文件失败,采集类型：{ConstHelper.GetType(info.dataType)}用户id:{urlId}文件地址：{url}" );
                    return false;
                }

                if (HttpHelper.DownFile(url, path, $"{Guid.NewGuid().ToString().Replace("-", "")}.mp4", _ipList[ip]) == true)
                {
                    Logging4net.WriteInfo($"下载文件成功！,采集类型：{ConstHelper.GetType(info.dataType)}用户id:{urlId}文件地址：{url}");
                    return true;
                } 
            } while (true); 
        }

        #endregion
         
        #region 私有方法

        public static string GetUrlId(string url)
        {
            if (url.IndexOf("api.huoshan.com") != -1)
            {
                url = url.Split('&')[0];
                url = url.Replace("video_id=", "★").Split('★')[1];
            }
            else if (url.IndexOf("video_id=") != -1)
            {
                url = url.Split('&')[0];
                url = url.Replace("video_id=", "★").Split('★')[1];
            }
            else if (url.IndexOf("meitudata.com") > -1)
            {
                url = (url.Split('/')[url.Split('/').Length - 1]).Replace(".mp4", "★").Split('★')[0];
            }
            else
            {
                url = (url.Split('/')[url.Split('/').Length - 1]).Replace(".mp4", "★").Split('★')[0];
            }

            return url;
        }

        public static string DecryptID(string ids)
        {
            #region 破解KEY

            var kk = new List<int>() { 65, 48, 77, 106, 90, 102, 77, 84, 89, 48, 78, 68, 65, 51, 77, 106 };

            #endregion

            #region 获取数据

            var e = ids.TrimStart(':').Split(':');
            string str = "";
            var index = 1;
            for (int x = 0; x < e.Length; x++)
            {
                var item = Convert.ToInt32(e[x]);
                var s = item - (255 & kk[(index - 1) % kk.Count]);

                str += Convert.ToChar(s);
                index++;
            }

            #endregion

            return str;
        }

        #endregion

        #region 旧代码

        //private void button1_Click(object sender, EventArgs e)
        //{ 
        //    var startId = StringHelper.ToNumber(this.StartID.Text);
        //    var endID = StringHelper.ToNumber(this.EndID.Text);
        //    var number = StringHelper.ToNumber(this.txtNumber.Text);
        //    var url = ConstHelper.GetUrl(this.DataType.SelectedIndex);
        //    var dataType = this.DataType.SelectedIndex;

        //    Task.Run(() =>
        //    {
        //        for (; startId <= endID; startId++)
        //        {
        //            var pageIndex = 0;
        //            var list = new List<VideoInfo>();

        //            #region 循环获取数据

        //            do
        //            {
        //                pageIndex++;
        //                int i = 0;

        //                goUrl:
        //                try
        //                {
        //                    Thread.Sleep(1000); // 发生错误是隔1秒执行 
        //                    var json = HttpHelper.Get(string.Format(url, startId, pageIndex));

        //                    if (json.IndexOf("data") > -1)
        //                    {
        //                        var models = SerializerHelper.JsonDeserialize<Videos>(json);

        //                        if (models.data != null && models.data.Any() == true)
        //                        {
        //                            list.AddRange(models.data.Select(c => new VideoInfo()
        //                            {
        //                                id = startId.ToString(),
        //                                video_img = c.video_img,
        //                                video_url = c.video_url,
        //                                dataType = dataType
        //                            }));

        //                            if (list.Count >= number)
        //                            {
        //                                break;
        //                            }
        //                        }
        //                    }
        //                    else
        //                    {
        //                        break;
        //                    }
        //                }
        //                catch (Exception ex)
        //                {
        //                    if (i < 3)
        //                    {
        //                        Thread.Sleep(1000 * 3); // 发生错误是隔2秒执行 
        //                        goto goUrl;
        //                    }

        //                    i++;
        //                }
        //            } while (true);

        //            #endregion

        //            #region 获取数据

        //            if (list.Any() == true)
        //            {
        //                for (int i = 0; i < list.Count; i++)
        //                {
        //                    if (i <= number)
        //                    {
        //                        _dowList.Enqueue(list[i]);
        //                    }
        //                    else
        //                    {
        //                        break;
        //                    }
        //                }
        //            }

        //            #endregion 
        //        }
        //    });

        //    Engine();
        //    //  MessageBox.Show("采集完成！");
        //}

        //#region 获取数据

        ///// <summary>
        ///// 获取CRM 资源
        ///// </summary>
        //public List<VideoInfo> GetResources()
        //{
        //    lock (_Lock)
        //    {
        //        if (_dowList != null && _dowList.Count > 0)
        //        {
        //            lock (_Lock)
        //            {
        //                if (_dowList != null && _dowList.Count > 0)
        //                {
        //                    var list = new List<VideoInfo>();

        //                    for (int i = 0; i < 5; i++)
        //                    {
        //                        VideoInfo temp = null;
        //                        if (_dowList.TryDequeue(out temp) == true)
        //                        {
        //                            list.Add(temp);
        //                        }
        //                        else
        //                        {
        //                            break;
        //                        } 

        //                    }

        //                    return list;
        //                }
        //            }
        //        }
        //    }

        //    return null;
        //}

        //#endregion

        //#region Engine

        ///// <summary>
        ///// 日志引擎
        ///// </summary>
        //public  void Engine()
        //{ 
        //    while (true)
        //    {
        //        var temp = GetResources();

        //        if (temp != null && temp.Any() == true)
        //        {

        //            temp.ForEach(item =>
        //            {
        //                DownloadT(item);
        //                this.Userid.Text = item.id; 
        //            });   
        //        }
        //    }
        //}


        ///// <summary>
        ///// 下载
        ///// </summary>
        ///// <param name="info"></param>
        ///// <returns></returns>
        //public bool DownloadT(VideoInfo info)
        //{ 
        //    int i = 0;
        //    goUrl:

        //    try
        //    {
        //        Form1.SID = info.id;
        //        var urlId = GetUrlId(info.video_url);
        //        var url = info.video_url.Replace(urlId, DecryptID(GetUrlId(urlId)));
        //        var path = $"{System.Environment.CurrentDirectory}\\{ConstHelper.GetType(info.dataType)}\\{DateTime.Now.ToString("yyyyMMdd")}\\{info.id}";

        //        if (url.IndexOf("http:") == -1)
        //        {
        //            url = "http:" + url;
        //        }
        //        HttpHelper.DownFile(url, path, $"{Guid.NewGuid().ToString().Replace("-", "")}.mp4");
        //    }
        //    catch (Exception ex)
        //    {
        //        if (i < 3)
        //        {
        //            Thread.Sleep(1000 * 10); // 发生错误是隔半分钟后再采集
        //            goto goUrl;
        //        }

        //        i++;
        //    }

        //    return false;
        //}

        ///// <summary>
        // /// 下载
        // /// </summary>
        // /// <param name="info"></param>
        // /// <returns></returns>
        //public async Task<bool> Download(VideoInfo info)
        //{
        //    return await Task.Run(() =>
        //    {
        //        int i = 0;
        //        goUrl:

        //        try
        //        { 
        //            Form1.SID = info.id;
        //            var urlId = GetUrlId(info.video_url);
        //            var url = info.video_url.Replace(urlId, DecryptID(GetUrlId(urlId)));
        //            var path = $"{System.Environment.CurrentDirectory}\\{ConstHelper.GetType(info.dataType)}\\{DateTime.Now.ToString("yyyyMMdd")}\\{info.id}";

        //            if (url.IndexOf("http:") == -1)
        //            {
        //                url = "http:" + url;
        //            }
        //            HttpHelper.DownFile(url, path, $"{Guid.NewGuid().ToString().Replace("-", "")}.mp4");
        //        }
        //        catch (Exception ex)
        //        {
        //            if (i < 3)
        //            {
        //                Thread.Sleep(1000 * 10); // 发生错误是隔半分钟后再采集
        //                goto goUrl;
        //            }

        //            i++;
        //        }

        //        return false;
        //    });
        //}

        //#endregion


        //#region 删除方法
        ////private void button2_Click(object sender, EventArgs e)
        ////{
        ////    OpenFileDialog dialog = new OpenFileDialog();
        ////    dialog.Multiselect = true;//该值确定是否可以选择多个文件
        ////    dialog.Title = "请选择文件夹";
        ////    dialog.Filter = "所有文件(*.*)|*.*";
        ////    string[] arr = new string[1];
        ////    string content = "";

        ////    if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        ////    {
        ////        var  path = dialog.FileName.ToString();

        ////        using (StreamReader sr = new StreamReader(path, System.Text.Encoding.UTF8))
        ////        {
        ////            arr = sr.ReadToEnd().TrimStart().Split(',').ToArray();
        ////        } 

        ////    }


        ////    if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        ////    {
        ////        var path = dialog.FileName.ToString();
        ////        using (StreamReader sr = new StreamReader(path, System.Text.Encoding.UTF8))
        ////        {
        ////            content = sr.ReadToEnd().TrimStart();
        ////        }
        ////    }

        ////    for (int i = 0; i < arr.Length; i++)
        ////    {
        ////        content = content.Replace("__Ox21703["+i+"]", arr[i]);


        ////    }

        ////    var s = content;
        ////}        #endregion

        //#endregion


        #endregion

        private void timer1_Tick(object sender, EventArgs e)
        {
            var endID = StringHelper.ToNumber(this.EndID.Text);
            this.Userid.Text = _userId.ToString();
            if (endID == _userId && _userId != 0)
            {
                this.button1.Enabled = true;
                this.button2.Enabled = true;
            }
            
        }
    }
}
 